<!DOCTYPE html>
<html lang="zh-CN" class="loading">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>学习react-readx状态管理 - Skyone-Blog</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="React,Node.js,react-redux,JavaScript,redux,"> 
    <meta name="description" content="Skyone技术博客,react-redux是react生态中的重要部分，是JavaScript状态容器，本文介绍了react状态管理的基本方法。"> 
    <meta name="author" content="王志伟"> 
    <link rel="alternative" href="atom.xml" title="Skyone-Blog" type="application/atom+xml"> 
    <link rel="icon" href="/img/favicon.png"> 
    
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">

    
<link rel="stylesheet" href="/css/diaspora.css">

    <!-- 看板娘
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css">
    <script src="/live2d-widget/autoload.js"></script>
    -->
    <!-- MD5 -->
    <script src="/js/md5.min.js"></script>
    <!-- MathJax -->
    
        <script type="text/x-mathjax-config">
        (function () {
            let target = document.getElementsByClassName("content")[0];
            MathJax.Hub.Config({
                tex2jax: {
                    inlineMath:  [ ["$", "$"] ],
                    displayMath: [ ["$$","$$"] ],
                    skipTags: ['script', 'noscript', 'style', 'textarea', 'pre','code','a'],
                    ignoreClass:"class1"
                }
            });
            MathJax.Hub.Queue(["Typeset",MathJax.Hub,target]);
        })();
    </script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>

    
<meta name="generator" content="Hexo 5.3.0"></head>

<body class="loading">
    <span id="config-title" style="display:none">Skyone-Blog</span>
    <div id="loader"></div>
    <div id="single">
    <div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <a class="iconfont icon-home image-icon" href="javascript:;" data-url="https://www.skyone.host"></a>
    <div title="播放/暂停" class="iconfont icon-play"></div>
    <h3 class="subtitle">学习react-readx状态管理</h3>
    <div class="social">
        <div>
            <div class="share">
                <a title="获取二维码" class="iconfont icon-scan" href="javascript:;"></a>
            </div>
            <div id="qr"></div>
        </div>
    </div>
    <div class="scrollbar"></div>
</div>

    <div class="section">
        <div class="article">
    <div class='main'>
        <h1 class="title">学习react-readx状态管理</h1>
        <div class="stuff">
            <span>八月 17, 2021</span>
            
  <ul class="post-tags-list" itemprop="keywords"><li class="post-tags-list-item"><a class="post-tags-list-link" href="/tags/JavaScript/" rel="tag">JavaScript</a></li><li class="post-tags-list-item"><a class="post-tags-list-link" href="/tags/Node-js/" rel="tag">Node.js</a></li><li class="post-tags-list-item"><a class="post-tags-list-link" href="/tags/React/" rel="tag">React</a></li></ul>


        </div>
        <div class="content markdown">
            <blockquote>
<p>本文针对React与Redux，如有错误，欢迎指正！</p>
<p>禁止全文转载，可以部分转载，转载请注明出处。</p>
</blockquote>
<h2 id="Redux是什么？"><a href="#Redux是什么？" class="headerlink" title="Redux是什么？"></a>Redux是什么？</h2><p>Redux 是 JavaScript 状态容器，提供可预测化的<strong>状态管理</strong>。</p>
<p>可以让你构建一致化的应用，运行于不同的环境（客户端、服务器、原生应用），并且易于测试。不仅于此，它还提供超爽的开发体验，比如有一个<a target="_blank" rel="noopener" href="https://github.com/gaearon/redux-devtools">时间旅行调试器可以编辑后实时预览</a>。</p>
<p>Redux除了和React一起用外，还支持其它界面库。 它体小精悍（只有2kB，包括依赖）。</p>
<h2 id="Why-redux？"><a href="#Why-redux？" class="headerlink" title="Why redux？"></a>Why redux？</h2><p>为什么React需要Redux，或者说为什么Redux适合与React合作呢？</p>
<p>第一个原因：</p>
<p>我们知道，React的数据是单向流动的，而根据React官方的<a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/docs/thinking-in-react.html#step-4-identify-where-your-state-should-live">React 哲学</a>中所述，</p>
<blockquote>
<p>React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. <strong>This is often the most challenging part for newcomers to understand,</strong> so follow these steps to figure it out:</p>
<p>For each piece of state in your application:</p>
<ul>
<li>Identify every component that renders something based on that state.</li>
<li>Find a common owner component (a single component above all the components that need the state in the hierarchy).</li>
<li>Either the common owner or another component higher up in the hierarchy should own the state.</li>
<li>If you can’t find a component where it makes sense to own the state, create a new component solely for holding the state and add it somewhere in the hierarchy above the common owner component.</li>
</ul>
</blockquote>
<p>这意味着什么？</p>
<blockquote>
<p>Either the common owner or another component higher up in the hierarchy should own the state.</p>
<ul>
<li>该共同所有者组件或者比它层级更高的组件应该拥有该 state。</li>
</ul>
</blockquote>
<p>意味着我们产生数据的地方（例如<code>input</code>标签）可能离储存数据的地方（上文中的更高级组件）之间可能隔了数层！</p>
<p>然而，想要控制一个输入标签至少需要两个传给子组件的参数（一个获取，一个传递），又隔了数层，麻烦不说，同时极大的增加了出错概率！当然，你也可以以高阶组件的方式将输入组件通过参数向下传递，可是这又破坏了代码结构，降低了代码可读性，提高了代码耦合性。</p>
<p>遇到这种情况，请试试Redux吧！</p>
<hr>
<p>第二个原因：</p>
<p>当你的页面（特别是SPA：单页应用程序）有很多状态需要管理时，你需要记住每一个状态的改变由谁产生，影响了谁，这并不是一件简单的事！有了Redux，你可以做到简单快捷的理顺这一切，并在调试时清楚的看到它们！</p>
<p><em>当然，Redux并不是只能和React配合使用，只要你想，可以在任何需要状态管理的地方使用它！</em></p>
<h2 id="Redux的核心概念"><a href="#Redux的核心概念" class="headerlink" title="Redux的核心概念"></a>Redux的核心概念</h2><p>正如Redux官网上说的那样，Redux本身很简单，以我所见，它主要分为：</p>
<ul>
<li>事件：<code>Action</code></li>
<li>处理者：<code>Reducer</code></li>
<li>仓库：<code>Store</code></li>
</ul>
<p>请允许我以我的理解试着解释它们：</p>
<h3 id="仓库Store"><a href="#仓库Store" class="headerlink" title="仓库Store"></a>仓库Store</h3><p>这个简单，就是储存数据的地方，我们通过</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123;createStore&#125; <span class="keyword">from</span> <span class="string">&#x27;redux&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> store = createStore();</span><br></pre></td></tr></table></figure>
<p>创建一个Store。</p>
<p>当然这个函数有几个参数，后面再作介绍，你只需要知道：</p>
<p><code>store</code>是集中储存数据的地方，它保证了数据只能由<code>action</code>经由<code>reducer</code>传递过来，自动传递到需要的地方。</p>
<p>出于方便考虑，<code>store</code>的初始值由<code>reducer</code>给出，这个后面再讲。</p>
<p><strong>注意</strong>：对于一个程序，你最好预先定义好一个<code>store</code>对象，并在后面严格遵守！</p>
<h3 id="事件Action"><a href="#事件Action" class="headerlink" title="事件Action"></a>事件Action</h3><p><code>Action</code>或许应该翻译成行动，但在这里，我认为事件更准确。</p>
<p>事件就是某一些改变了数据的事情，它是唯一能改变<code>store</code>的方法，任何一个绑定了<code>redux</code>的组件都可以产生<code>action</code>，但你可以通过定义并限制<code>action</code>的使用类型来限制组件能改变的数据。</p>
<p>例如：对应一个商店系统，你定义了许多<code>action</code>，其中<code>action A</code>可以改变<code>store</code>中商品的存货，<code>action B</code>可以改变<code>store</code>中商品的单价。假设有一个点击从后台获取存货数量的组件，那么只需要限制它只能使用<code>action A</code>即可。</p>
<p><code>action</code>本质上是一个描述数据改变的对象，这个对象的“形状”是任意的，但对于每一个程序，你最好定义一个统一标准，例如：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">&quot;type&quot;</span>: <span class="string">&quot;ChangeScores&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;data&quot;</span>: &#123;</span><br><span class="line">        <span class="attr">&quot;scores&quot;</span>: <span class="number">233</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="处理者Reducer"><a href="#处理者Reducer" class="headerlink" title="处理者Reducer"></a>处理者Reducer</h3><p><em><code>reducer</code>的意思是还原剂，搞不懂。。。</em></p>
<p>处理者<code>reducer</code>很好理解，就是根据<code>action</code>的类型，将<code>action</code>中的数据取出来，合并到<code>store</code>中，它是一个函数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myReducer = <span class="function">(<span class="params">action, store</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 原store不可修改，需要复制一份</span></span><br><span class="line">    store = &#123;...store&#125;;		<span class="comment">// 也可以使用 `Object.assign(&#123;&#125;, store)`</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 数据合并操作</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">return</span> store;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>一个<code>store</code>有且只能有一个<code>reducer</code>，因此这个<code>reducer</code>需要处理所有种类的<code>action</code>，你可以这么写：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> doChangeScores = <span class="function">(<span class="params">data, store</span>) =&gt;</span> &#123;</span><br><span class="line">    store.scores = data.scores;</span><br><span class="line">    <span class="keyword">return</span> store;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> myReducer = <span class="function">(<span class="params">action, store = &#123;<span class="regexp">/* store的初始值 */</span>&#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    store = &#123;...store&#125;;</span><br><span class="line">    <span class="keyword">switch</span> (action.type) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&quot;ChangeScores&quot;</span>:</span><br><span class="line">            <span class="keyword">return</span> doChangeScores(action.data, store);</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&quot;ChangeXXXXX&quot;</span>:</span><br><span class="line">            <span class="comment">// ............</span></span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">return</span> store;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (action.type === <span class="string">&quot;ChangeScores&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> store;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>入=如上例所示，可以在<code>reducer</code>中方便的给出<code>store</code>的初始值。</p>
<p>至于为什么不能之间改变<code>store</code>，而是复制一份，因为<code>Redux</code>内部需要比较<code>store</code>是否改变了，借此判断受影响组件是否更新。</p>
<h3 id="他们的关系"><a href="#他们的关系" class="headerlink" title="他们的关系"></a>他们的关系</h3><p>下面用一段<del>生动的</del>话来讲解他们的关系：</p>
<hr>
<p>现有三个人分析“巨硬”公司的市场行情，</p>
<p>数据收集师<code>action</code>发现“巨硬”公司股票又涨了，他告诉会计<code>reducer</code>：“喂，老兄，‘巨硬’公司股票又涨了<code>aaa</code>。”</p>
<p>会计<code>reducer</code>听到后，查询数据库中上月的“巨硬”公司股票，并做出了计算，但是<code>reducer</code>不会修改数据库，只能把数据库管理员<code>store</code>叫来，告诉他：“‘巨硬’公司这个月股票<code>bbb</code>，增长了<code>ccc</code>”。</p>
<p>数据库管理员<code>store</code>回答：“了解！”并在数据库里加上：“八月‘巨硬’公司月股票<code>bbb</code>，增长了<code>c%</code>”。然后通知领导把数据拿走了，用来指定下一步计划。。。</p>
<hr>
<p>简单来说：</p>
<p><code>action</code>通知<code>reducer</code>数据改了，<code>reducer</code>将数据合并，交给<code>store</code>，<code>store</code>修改自身数据，通知数据的使用者。</p>
<h3 id="connect函数"><a href="#connect函数" class="headerlink" title="connect函数"></a><code>connect</code>函数</h3><p><code>connect</code>函数非常重要！它描述了组件如何连接<code>store</code>！</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)l</span><br></pre></td></tr></table></figure>
<p>主要需要了解前两个参数</p>
<ol>
<li><p><code>mapStateToProps(state, [ownProps]): stateProps</code></p>
<p> 这是一个函数，提供从<code>state</code>到<code>props</code>的映射，也就是说，定义该组件需要从<code>store</code>中获取什么到<code>props</code>中。</p>
<p> 这将导致：<code>store</code>刷新时该组件重新渲染。</p>
</li>
<li><p><code>mapDispatchToProps(dispatch, [ownProps]): dispatchProps</code></p>
<p> 这是一个函数，提供<code>action</code>发送到<code>reducer</code>的手段，它返回一个对象，该对象会合并到组件的<code>props</code>中，对象里全是函数，这些函数根据<code>mapDispatchToProps</code>接收的<code>dispath</code>参数调用<code>reducer</code>，具体请看下面的例子。</p>
</li>
<li><p><code>mergeProps(stateProps, dispatchProps, ownProps): props</code></p>
<p> 一个函数，将上两个函数的执行结果传入，并传入组件自身的<code>props</code>，返回值作为组件的实际<code>props</code></p>
<p> 例如，它的<strong>默认值</strong>是（**<em>重点理解！**</em>）</p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(stateProps, dispatchProps, ownProps) =&gt; &#123;<span class="built_in">Object</span>.assign(&#123;&#125;, stateProps, dispatchProps, ownProps)&#125;;</span><br></pre></td></tr></table></figure></li>
<li><p><code>options</code></p>
<p> 一个对象，指定<code>connector</code>的行为。</p>
</li>
</ol>
<h2 id="一个例子"><a href="#一个例子" class="headerlink" title="一个例子"></a>一个例子</h2><p>安装依赖</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add redux react-readx</span><br></pre></td></tr></table></figure>
<p><code>store.js</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; createStore &#125; <span class="keyword">from</span> <span class="string">&quot;redux&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reducer</span> (<span class="params">state = &#123; source: <span class="number">0</span> &#125;, action</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (action.type) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&quot;Scores/Change&quot;</span>:</span><br><span class="line">            <span class="keyword">return</span> &#123; <span class="attr">source</span>: state.scores + action.count &#125;;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">return</span> state;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> createStore(reducer);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 产生其中一种 `action` 的工厂函数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> ChangeScores = <span class="function">(<span class="params">count</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        type: <span class="string">&quot;Scores/Change&quot;</span>,</span><br><span class="line">        count: count</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><code>ChangeScores.jsx</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; Component &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> MyButton <span class="keyword">from</span> <span class="string">&#x27;./MyButton&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> Input <span class="keyword">from</span> <span class="string">&#x27;./Input&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ChangeScores</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(props);</span><br><span class="line">        <span class="built_in">this</span>.state = &#123; <span class="attr">value</span>: <span class="number">0</span> &#125;;</span><br><span class="line">        <span class="built_in">this</span>.handleChangeValue = <span class="built_in">this</span>.handleChangeValue.bind(<span class="built_in">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">handleChangeValue</span>(<span class="params">value</span>)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.setState(&#123;</span><br><span class="line">            value: value</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;Input handleChangeValue=&#123; <span class="built_in">this</span>.handleChangeValue &#125;/&gt;</span><br><span class="line">                &lt;MyButton value=&#123;<span class="built_in">this</span>.state.value&#125;&gt;Change Scores&lt;/MyButton&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> ChangeScores;</span><br></pre></td></tr></table></figure>
<p><code>MyButton.jsx</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; Component &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; connect &#125; <span class="keyword">from</span> <span class="string">&#x27;react-redux&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; ChangeScores &#125; <span class="keyword">from</span> <span class="string">&#x27;../redux/store&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyButton</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(props);</span><br><span class="line">        <span class="built_in">this</span>.onChangeScores = <span class="built_in">this</span>.onChangeScores.bind(<span class="built_in">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">onChangeSource</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.props.onChangeScores(<span class="built_in">this</span>.props.value);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            &lt;button onClick=&#123;<span class="built_in">this</span>.onChangeScores&#125;&gt;&#123; <span class="built_in">this</span>.props.children &#125;&lt;/button&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">mapDispatchToProps</span>(<span class="params">dispath</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        onChangeScores: <span class="function">(<span class="params">value</span>) =&gt;</span> dispath(ChangeScores(value))</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> connect(<span class="literal">null</span>, mapDispatchToProps)(MyButton);</span><br></pre></td></tr></table></figure>
<p>这里的<code>ChangeScores()</code>是一个工厂函数，产生改变<code>scores</code>的<code>action</code></p>
<p><code>Input.jsx</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; Component &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Input</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(props);</span><br><span class="line">        <span class="built_in">this</span>.onChangeValue = <span class="built_in">this</span>.onChangeValue.bind(<span class="built_in">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">onChangeValue</span>(<span class="params">e</span>)</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> value = <span class="built_in">parseInt</span>(e.target.value);</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">Number</span>.isInteger(value)) &#123;</span><br><span class="line">            <span class="built_in">this</span>.props.handleChangeValue(value);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            &lt;label&gt;value&lt;input onChange=&#123;<span class="built_in">this</span>.onChangeValue&#125; type=<span class="string">&quot;text&quot;</span>&gt;&lt;<span class="regexp">/input&gt;&lt;/</span>label&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> Input;</span><br></pre></td></tr></table></figure>
<p><code>ShowScores.jsx</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; Component &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; connect &#125; <span class="keyword">from</span> <span class="string">&#x27;react-redux&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ShowScores</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            &lt;h2&gt;Source: &#123; <span class="built_in">this</span>.props.source &#125;&lt;/h2&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">mapStateToProps</span>(<span class="params">state</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        source: state.source</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> connect(mapStateToProps)(ShowScores);</span><br></pre></td></tr></table></figure>
<p><code>App.jsx</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; Component &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> ChangeScores <span class="keyword">from</span> <span class="string">&#x27;../components/ChangeScores&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> ShowScores <span class="keyword">from</span> <span class="string">&#x27;../components/ShowScores&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;ShowScores/&gt;</span><br><span class="line">                &lt;ChangeScores/&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> App;</span><br></pre></td></tr></table></figure>
<p><img src="https://tc.skyone.host/blog/post/%E5%AD%A6%E4%B9%A0react-readx%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/%E4%BE%8B%E5%AD%90.png" alt="例子"></p>

            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls" data-autoplay="false">
                <source type="audio/mpeg" src="">
            </audio>
            
                <ul id="audio-list" style="display:none">
                    
                        
                            <li title='0' data-url='https://tc.skyone.host/blog/music/%E6%B4%9B%E5%A4%A9%E4%BE%9D%20-%20%E5%A4%9C%E8%88%AA%E6%98%9F.flac'></li>
                        
                    
                        
                            <li title='1' data-url='https://tc.skyone.host/blog/music/%E6%B4%9B%E5%A4%A9%E4%BE%9D%20-%20%E8%8C%89%E8%8E%89%E8%8A%B1.mp3'></li>
                        
                    
                        
                            <li title='2' data-url='https://tc.skyone.host/blog/music/%E8%B5%A4%E7%BE%BD%20-%20%E4%B8%87%E5%8F%A4%E7%94%9F%E9%A6%99.flac'></li>
                        
                    
                        
                            <li title='3' data-url='https://tc.skyone.host/blog/music/%E6%B4%9B%E5%A4%A9%E4%BE%9D%20-%20%E4%B8%BA%E8%B0%81%E8%80%8C%E4%B8%BA.mp3'></li>
                        
                    
                        
                            <li title='4' data-url='https://tc.skyone.host/blog/music/%E4%B9%90%E6%AD%A3%E7%BB%AB%20-%20Faded.mp3'></li>
                        
                    
                        
                            <li title='5' data-url='https://tc.skyone.host/blog/music/bilibili2018%20-%20%E8%87%B3%E5%B0%8A%E9%A9%AC%E7%94%B2.flac'></li>
                        
                    
                </ul>
            
        </div>
        
    <div id='gitalk-container' class="comment link"
		data-enable='true'
        data-ae='true'
        data-ci='d5e197ef955b7f3268e5'
        data-cs='7d4feed7a179ad28943b0865b7970814073145ad'
        data-r='blog-gitalk'
        data-o='skyone-wzw'
        data-a='skyone-wzw'
        data-d='false'
    >查看评论</div>


    </div>
    
        <div class='side'>
			<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#Redux%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F"><span class="toc-number">1.</span> <span class="toc-text">Redux是什么？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Why-redux%EF%BC%9F"><span class="toc-number">2.</span> <span class="toc-text">Why redux？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Redux%E7%9A%84%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="toc-number">3.</span> <span class="toc-text">Redux的核心概念</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%93%E5%BA%93Store"><span class="toc-number">3.1.</span> <span class="toc-text">仓库Store</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%8B%E4%BB%B6Action"><span class="toc-number">3.2.</span> <span class="toc-text">事件Action</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E8%80%85Reducer"><span class="toc-number">3.3.</span> <span class="toc-text">处理者Reducer</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%96%E4%BB%AC%E7%9A%84%E5%85%B3%E7%B3%BB"><span class="toc-number">3.4.</span> <span class="toc-text">他们的关系</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#connect%E5%87%BD%E6%95%B0"><span class="toc-number">3.5.</span> <span class="toc-text">connect函数</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90"><span class="toc-number">4.</span> <span class="toc-text">一个例子</span></a></li></ol>	
        </div>
    
</div>


    </div>
</div>
</body>

<script src="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>


<script src="//lib.baomitu.com/jquery/1.8.3/jquery.min.js"></script>
<script src="/js/plugin.js"></script>
<script src="/js/typed.js"></script>
<script src="/js/skyone.min.js"></script>


<link rel="stylesheet" href="/photoswipe/photoswipe.css">
<link rel="stylesheet" href="/photoswipe/default-skin/default-skin.css">


<script src="/photoswipe/photoswipe.min.js"></script>
<script src="/photoswipe/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>




</html>
